package session.stateless;

import entity.CuisinePrefEntity;
import entity.InterestPrefEntity;
import entity.PersonalPrefEntity;
import util.entityhelper.TouristAccountState;
import entity.TouristAccountEntity;
import entity.TouristEntity;
import util.enumeration.Country;
import exception.ExistException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.Remove;
import javax.ejb.Stateless;
import javax.persistence.Query;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import util.enumeration.Gender;

/**
 *
 * @author Swee Zhi
 */
@Stateless
public class TouristAccountSessionBean {
    @PersistenceContext
    EntityManager em;
    
    private String selectedLocale;

    private TouristEntity touristEntity;
    private TouristAccountEntity touristAccountEntity;
    
    // EXCEPTION
    private SystemMessagesBean systemMessages;

    /** Creates a new instance of TouristAccountSessionBean */
    public TouristAccountSessionBean() {
        systemMessages = new SystemMessagesBean();
    }
    
    public void setSelectedLocale(String locale) {
        this.selectedLocale = locale;
    }

    public void createTouristAccount(String username, String password, // username = primary email
                                     String lastName, String firstName, 
                                     Gender gender, Date birthdate, 
                                     Country country, String locale, 
                                     String email, String emailSecondary,
                                     List<CuisinePrefEntity> cuisinePrefList, List<InterestPrefEntity> interestPrefList) throws ExistException {
        
        // tourist user account entity does not exist;
        if (touristAccountEntity == null && touristEntity == null) {
            touristAccountEntity = new TouristAccountEntity();
            touristEntity = new TouristEntity();
            
            // auto get system time for registration date
            Calendar cal = Calendar.getInstance();
            Date creationDate = cal.getTime();
            Date passwordChangeDate = cal.getTime();
            
            touristEntity.create(lastName, firstName, gender, birthdate, country, locale, email, emailSecondary);
            PersonalPrefEntity personalPref = new PersonalPrefEntity();
            personalPref.setCuisinePrefs(cuisinePrefList);
            personalPref.setInterestPrefs(interestPrefList);
            touristEntity.setPersonalPref(personalPref);
            
            touristAccountEntity.create(username, password, creationDate, passwordChangeDate);
            touristAccountEntity.setActivationStatus(true);
            touristAccountEntity.setTourist(touristEntity);
            
            em.persist(touristAccountEntity);
        }
        else {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("TOURIST_ACCT_EXISTS", selectedLocale));
        }
    }
    
    public void updateTouristAccount(Long touristAccountId, String newPassword) throws ExistException {
        // find account in persistence context
        touristAccountEntity = em.find(TouristAccountEntity.class, touristAccountId);
        
        // tourist user account entity does not exist;
        if (touristAccountEntity == null) {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("TOURIST_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            // check and update password and password change date fields
            String password = touristAccountEntity.getPassword();
            Date passwordChangeDate = touristAccountEntity.getPasswordChangeDate();
            if (!password.equals(newPassword)) {
                // auto get system time for registration date
                Calendar cal = Calendar.getInstance();
                passwordChangeDate = cal.getTime();
            }
            System.out.println("password: " + newPassword);
            touristAccountEntity.update(newPassword, passwordChangeDate);
            em.persist(touristAccountEntity);
            em.flush();
        }
    }
    
    public void updateTourist(Long touristId, Country country, String locale, String emailSecondary) throws ExistException {
        // find tourist in persistence context
        touristEntity = em.find(TouristEntity.class, touristId);
        
        // tourist entity does not exist;
        if (touristEntity == null) {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("TOURIST_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            touristEntity.update(country, locale, emailSecondary);
            em.persist(touristEntity);
            em.flush();
        }
    }
    
    public void updateTouristPersonalPrefs(Long touristId, List<CuisinePrefEntity> newCuisinePrefList, List<InterestPrefEntity> newInterestPrefList) throws ExistException {
        // find tourist in persistence context
        touristEntity = em.find(TouristEntity.class, touristId);
        
        // tourist entity does not exist;
        if (touristEntity == null) {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("TOURIST_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            touristEntity.getPersonalPref().getCuisinePrefs().clear();
            touristEntity.getPersonalPref().getInterestPrefs().clear();
            
            touristEntity.getPersonalPref().setCuisinePrefs(newCuisinePrefList);
            touristEntity.getPersonalPref().setInterestPrefs(newInterestPrefList);
            
            em.persist(touristEntity);
            em.flush();
        }
    }
    
    
    
    
    public TouristAccountState getTouristAccountByID(Long touristUserAccountId) 
            throws ExistException {
        TouristAccountState touristUserAccountState = null;

        // find account id
        Query q = em.createQuery("SELECT a FROM TouristAcct a WHERE a.id = :accId");
        q.setParameter("accId", touristUserAccountId);

        if (q.getResultList().isEmpty()) {
            // show exception message using SystemMessage bean
            throw new ExistException(systemMessages.getSystemMessage("TOURIST_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            TouristAccountEntity a = (TouristAccountEntity)q.getSingleResult();
            touristUserAccountState = new TouristAccountState(
                    a.getId(),
                    a.getUsername(),
                    a.getPassword(),
                    a.getCreationDate(),
                    a.getTourist());
        }
        return touristUserAccountState;
    }
    
    public TouristAccountState getTouristAccountByUsername(String username) // is primary email..
            throws ExistException {
        TouristAccountState touristAccountState = null;

        // find username
        Query q = em.createQuery("SELECT a FROM TouristAcct a WHERE a.username = :uname");
        q.setParameter("uname", username);

        // result has nothing...
        if (q.getResultList().isEmpty()) {
            // show exception message using SystemMessage bean
            System.out.println("selectLocale: " + selectedLocale);
            String statusMessage = systemMessages.getSystemMessage("TOURIST_ACCT_DOES_NOT_EXIST", selectedLocale);
            System.out.println(statusMessage);
            throw new ExistException(statusMessage);
        }
        // if result has something...
        else {
            TouristAccountEntity a = (TouristAccountEntity)q.getSingleResult();
            System.out.println(a.getUsername() + "" + a.getPassword());
            touristAccountState = new TouristAccountState(
                    a.getId(),
                    a.getUsername(),
                    a.getPassword(),
                    a.getCreationDate(),
                    a.getTourist());
        }
        return touristAccountState;
    }
    
//    public Set<StudentDetailsState> getStudents() throws ExistException {
//        Query q = em.createQuery("SELECT s FROM Student s");
//        Set stateSet = new HashSet();
//
//        if (q.getResultList().isEmpty()) {
//            throw new ExistException("No students found in database!");
//        }
//        else {
//            for (Object o: q.getResultList()) {
//                StudentEntity s = (StudentEntity)o;
//                StudentDetailsState sdState = new StudentDetailsState(
//                        s.getStdId(), s.getName(),
//                        s.getAddress().getAddId(),
//                        s.getAddress().getAddressLine1(),
//                        s.getAddress().getAddressLine2(),
//                        s.getAddress().getPostalCode(),
//                        s.getContactNumber().getCttId(),
//                        s.getContactNumber().getPhoneNumber());
//                stateSet.add(sdState);
//            }
//        }
//        return stateSet;
//    }

//    public Set<StudentDetailsState> getStudentOrStudentsByName(String name)
//            throws ExistException {
//        Set stateSet = new HashSet();
//        StudentDetailsState sdState = null;
//
//        // find name in database before creation
//        Query q = em.createQuery("SELECT s FROM Student s WHERE s.name = :sName");
//        q.setParameter("sName", name);
//
//        if (q.getResultList().isEmpty()) {
//            throw new ExistException("No such student found in database!");
//        }
//        else {
//            // only 1 person with the specified name
//            if (q.getResultList().size() == 1) {
//                StudentEntity s = (StudentEntity)q.getSingleResult();
//                sdState = new StudentDetailsState(
//                        s.getStdId(), s.getName(),
//                        s.getAddress().getAddId(),
//                        s.getAddress().getAddressLine1(),
//                        s.getAddress().getAddressLine2(),
//                        s.getAddress().getPostalCode(),
//                        s.getContactNumber().getCttId(),
//                        s.getContactNumber().getPhoneNumber());
//                stateSet.add(sdState);  // add only 1
//            }
//            // if 2 or more people have the same name, return the list for user to choose
//            else if (q.getResultList().size() > 1) {
//                for (int i = 0; i < q.getResultList().size(); i++) {
//                    StudentEntity s = (StudentEntity)q.getResultList().get(i);
//                    sdState = new StudentDetailsState(
//                            s.getStdId(), s.getName(),
//                            s.getAddress().getAddId(),
//                            s.getAddress().getAddressLine1(),
//                            s.getAddress().getAddressLine2(),
//                            s.getAddress().getPostalCode(),
//                            s.getContactNumber().getCttId(),
//                            s.getContactNumber().getPhoneNumber());
//                    stateSet.add(sdState);
//                }
//            }
//        }
//        return stateSet;
//    }
    
//    public void deleteTouristAccount(Long touristAccountId)
//        throws ExistException {
//
//        touristAccountEntity = em.find(TouristAccountEntity.class, touristAccountId);
//
//        // tourist user account entity does not exist;
//        if (touristAccountEntity == null) {
//            // EXCEPTION
//            throw new ExistException(systemMessages.getSystemMessage("TOURIST_ACCT_DOES_NOT_EXIST", selectedLocale));
//        }
//        else {
//            touristEntity = em.find(TouristEntity.class, touristAccountEntity.getTourist().getId());
////            if (touristAccountEntity.getRegistrations().size() > 0) {
////                throw new ExistException("Student has already registered.");
////            }
////
////            contactNumberEntity = studentEntity.getContactNumber();
////            addressEntity = studentEntity.getAddress();
////
////            em.remove(contactNumberEntity);
//            em.remove(touristEntity);
//            em.remove(touristAccountEntity);
//        }
//    }
    
    public boolean inactivateTouristAccount(Long touristAccountId) throws ExistException {
        touristAccountEntity = em.find(TouristAccountEntity.class, touristAccountId);
        
        // tourist user account entity does not exist;
        if (touristAccountEntity == null) {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("TOURIST_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            touristAccountEntity.setActivationStatus(false);
            em.persist(touristAccountEntity);
            return true;
        }
    }

    @Remove
    public void remove() {
        System.out.println("TouristAccountManagerBean:remove()");
    }
}
